package com.maxlen.coupon.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maxlen.common.constant.CouponConstant;
import com.maxlen.common.utils.*;
import com.maxlen.coupon.dao.CouponDao;
import com.maxlen.coupon.entity.CouponEntity;
import com.maxlen.coupon.entity.CouponHistoryEntity;
import com.maxlen.coupon.entity.CouponSpuCategoryRelationEntity;
import com.maxlen.coupon.entity.CouponSpuRelationEntity;
import com.maxlen.coupon.entity.dto.CouponAddUpdateDTO;
import com.maxlen.coupon.entity.to.LoginInfoTO;
import com.maxlen.coupon.entity.to.MemberEntityTO;
import com.maxlen.coupon.entity.vo.CouponReceptionVO;
import com.maxlen.coupon.feign.GoodsFeignService;
import com.maxlen.coupon.feign.MemberFeignService;
import com.maxlen.coupon.interceptor.LoginInterceptor;
import com.maxlen.coupon.service.CouponHistoryService;
import com.maxlen.coupon.service.CouponService;
import com.maxlen.coupon.service.CouponSpuCategoryRelationService;
import com.maxlen.coupon.service.CouponSpuRelationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;


@Service("couponService")
public class CouponServiceImpl extends ServiceImpl<CouponDao, CouponEntity> implements CouponService {

    @Autowired
    private MemberFeignService memberFeignService;

    @Autowired
    private CouponHistoryService couponHistoryService;

    @Autowired
    private CouponSpuRelationService couponSpuRelationService;

    @Autowired
    private CouponSpuCategoryRelationService couponSpuCategoryRelationService;

    @Autowired
    private GoodsFeignService goodsFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        LambdaQueryWrapper<CouponEntity> wrapper = new LambdaQueryWrapper<>();
        String key = params.get(Constant.KEY) == null ? null : params.get(Constant.KEY).toString();
        if(StringUtils.hasText(key)) {
            wrapper.like(CouponEntity::getId, key).or()
                    .like(CouponEntity::getCouponName, key);
        }
        IPage<CouponEntity> page = this.page(
                new Query<CouponEntity>().getPage(params),
                wrapper.orderByDesc(CouponEntity::getStartTime)
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public R publishCoupon(String couponId) {

        CouponEntity couponEntity = baseMapper.selectById(couponId);

        if(new Date(System.currentTimeMillis()).compareTo(couponEntity.getEndTime()) >= 0){
            return R.error(ResultCode.COUPON_OVERTIME);
        }

        if(!CouponConstant.CouponType.ALL.getCode().equals(couponEntity.getCouponType())
                && new Date(System.currentTimeMillis()).compareTo(couponEntity.getEnableEndTime()) >= 0){
            return R.error(ResultCode.COUPON_OVERTIME);
        }

        // 判断分为后台发放和自行领取
        if(CouponConstant.CouponType.ALL.getCode().equals(couponEntity.getCouponType())) {
            R memberByCouponPublish = memberFeignService.getMemberByCouponPublish();
            if(!memberByCouponPublish.isOk()){
                return R.error(ResultCode.MEMBER_SERVICE_ERROR);
            }

            List<MemberEntityTO> memberEntityTOList = memberByCouponPublish.getData(new TypeReference<List<MemberEntityTO>>() {});
            List<CouponHistoryEntity> couponHistoryEntityArrayList = new ArrayList<>();
            for (MemberEntityTO memberEntityTO : memberEntityTOList) {
                for (int i = 0; i < couponEntity.getPerLimit(); i++) {
                    CouponHistoryEntity couponHistoryEntity = new CouponHistoryEntity();
                    couponHistoryEntity.setCouponId(Long.valueOf(couponId));
                    couponHistoryEntity.setMemberId(memberEntityTO.getId());
                    couponHistoryEntity.setMemberNickName(memberEntityTO.getNickname());
                    couponHistoryEntity.setGetType(CouponConstant.CouponHistoryGetType.GIVE.getCode());
                    couponHistoryEntity.setCreateTime(new Date(System.currentTimeMillis()));
                    couponHistoryEntity.setUseType(CouponConstant.CouponHistoryUseType.NO_USE.getCode());
                    couponHistoryEntityArrayList.add(couponHistoryEntity);
                }
            }

            couponEntity.setPublishCount(couponHistoryEntityArrayList.size());

            couponHistoryService.saveBatch(couponHistoryEntityArrayList);
        }

        couponEntity.setPublish(CouponConstant.CouponPublish.PUBLISH.getCode());

        baseMapper.updateById(couponEntity);

        return R.ok();

    }

    @Override
    @Transactional
    public R saveCoupon(CouponAddUpdateDTO couponAddUpdateDTO) {
        CouponEntity couponEntity = couponAddUpdateDTO.getCouponEntity();
        List<CouponAddUpdateDTO.CouponDTO> couponDTO = couponAddUpdateDTO.getCouponDTO();
        if(couponDTO.isEmpty() && !CouponConstant.CouponUseType.ALL.getCode().equals(couponEntity.getUseType())){
            return R.error(ResultCode.COUPON_NO_SPU);
        }

        couponEntity.setId(null);
        baseMapper.insert(couponEntity);
        System.out.println(couponEntity);

        addCategoryAndSpuRelation(couponEntity, couponDTO);

        return R.ok();
    }

    @Override
    @Transactional
    public R updateCoupon(CouponAddUpdateDTO couponAddUpdateDTO) {
        CouponEntity couponEntity = couponAddUpdateDTO.getCouponEntity();

        List<CouponAddUpdateDTO.CouponDTO> couponDTO = couponAddUpdateDTO.getCouponDTO();
        if(couponDTO.isEmpty() && !CouponConstant.CouponUseType.ALL.getCode().equals(couponEntity.getUseType())){
            return R.error(ResultCode.COUPON_NO_ATTR);
        }

        couponSpuRelationService.deleteBatchByCouponId(Collections.singletonList(couponEntity.getId()));
        couponSpuCategoryRelationService.deleteBatchByCouponId(Collections.singletonList(couponEntity.getId()));

        addCategoryAndSpuRelation(couponEntity, couponDTO);

        if(CouponConstant.CouponType.ALL.getCode().equals(couponEntity.getCouponType())){
            couponEntity.setEnableStartTime(null);
            couponEntity.setEnableEndTime(null);
            couponEntity.setCouponImg(null);
        }
        baseMapper.updateById(couponEntity);

        return R.ok();
    }

    @Override
    @Transactional
    public R deleteCoupon(List<Long> asList) {
        couponSpuRelationService.deleteBatchByCouponId(asList);
        couponSpuCategoryRelationService.deleteBatchByCouponId(asList);
        couponHistoryService.deleteBatchByCouponId(asList);
        baseMapper.deleteBatchIds(asList);
        return R.ok();
    }

    @Override
    public R infoCoupon(Long id) {
        CouponAddUpdateDTO couponAddUpdateDTO = new CouponAddUpdateDTO();
        List<CouponAddUpdateDTO.CouponDTO> couponDTOList = new ArrayList<>();
        CouponEntity couponEntity = baseMapper.selectById(id);
        couponAddUpdateDTO.setCouponEntity(couponEntity);

        // 指定分类
        if(CouponConstant.CouponUseType.CATEGORY.getCode().equals(couponEntity.getUseType())){
            List<CouponSpuCategoryRelationEntity> couponSpuCategoryRelationEntityList = couponSpuCategoryRelationService.getBaseMapper().selectList(new LambdaQueryWrapper<CouponSpuCategoryRelationEntity>()
                    .eq(CouponSpuCategoryRelationEntity::getCouponId, id));
            CouponAddUpdateDTO.CouponDTO couponDTO = new CouponAddUpdateDTO.CouponDTO();
            for (CouponSpuCategoryRelationEntity couponSpuCategoryRelationEntity : couponSpuCategoryRelationEntityList) {
                couponDTO.setId(couponSpuCategoryRelationEntity.getCategoryId());
                couponDTO.setName(couponSpuCategoryRelationEntity.getCategoryName());
                couponDTOList.add(couponDTO);
            }
        }

        // 指定商品
        if(CouponConstant.CouponUseType.PRODUCT.getCode().equals(couponEntity.getUseType())){
            List<CouponSpuRelationEntity> couponSpuRelationEntityList = couponSpuRelationService.getBaseMapper().selectList(new LambdaQueryWrapper<CouponSpuRelationEntity>()
                    .eq(CouponSpuRelationEntity::getCouponId, id));
            for (CouponSpuRelationEntity couponSpuRelationEntity : couponSpuRelationEntityList) {
                CouponAddUpdateDTO.CouponDTO couponDTO = new CouponAddUpdateDTO.CouponDTO();
                couponDTO.setId(couponSpuRelationEntity.getSpuId());
                couponDTO.setName(couponSpuRelationEntity.getSpuName());
                couponDTOList.add(couponDTO);
            }
        }
        couponAddUpdateDTO.setCouponDTO(couponDTOList);

        return R.ok().setData(couponAddUpdateDTO);
    }

    @Override
    public R getUseTypeList(String id, Integer useType) {
        if(CouponConstant.CouponUseType.CATEGORY.getCode().equals(useType)){
            List<CouponSpuCategoryRelationEntity> couponSpuCategoryRelationEntityList = couponSpuCategoryRelationService.getBaseMapper().selectList(new LambdaQueryWrapper<CouponSpuCategoryRelationEntity>()
                    .eq(CouponSpuCategoryRelationEntity::getCouponId, id)
                    .select(CouponSpuCategoryRelationEntity::getCategoryName));

            List<String> collect = couponSpuCategoryRelationEntityList.stream().map(CouponSpuCategoryRelationEntity::getCategoryName).collect(Collectors.toList());
            return R.ok().setData(collect);
        }

        if(CouponConstant.CouponUseType.PRODUCT.getCode().equals(useType)){
            List<CouponSpuRelationEntity> couponSpuRelationEntityList = couponSpuRelationService.getBaseMapper().selectList(new LambdaQueryWrapper<CouponSpuRelationEntity>()
                    .eq(CouponSpuRelationEntity::getCouponId, id)
                    .select(CouponSpuRelationEntity::getSpuName));

            List<String> collect = couponSpuRelationEntityList.stream().map(CouponSpuRelationEntity::getSpuName).collect(Collectors.toList());
            return R.ok().setData(collect);
        }

        return R.ok();
    }

    @Override
    public R getCategoryImage(List<Long> categoryIdList) {
        R imageByCategoryIdList = goodsFeignService.getImageByCategoryIdList(categoryIdList);
        if(!imageByCategoryIdList.isOk()){
            return R.error(ResultCode.PRODUCT_SERVICE_ERROR);
        }

        return imageByCategoryIdList;
    }

    @Override
    public R getSpuImage(List<Long> spuIdList) {
        R imageByCategoryIdList = goodsFeignService.getImageBySpuIdList(spuIdList);
        if(!imageByCategoryIdList.isOk()){
            return R.error(ResultCode.PRODUCT_SERVICE_ERROR);
        }

        return imageByCategoryIdList;
    }

    @Override
    public R getReceiveCoupon() {
        LoginInfoTO loginInfoTO = LoginInterceptor.threadLocalID.get();
        LoginInterceptor.threadLocalID.remove();
        // 获取用户已经领取并且领取类型是自行领取的优惠券id
        List<CouponHistoryEntity> couponHistoryEntityList = couponHistoryService.getBaseMapper().selectList(new LambdaQueryWrapper<CouponHistoryEntity>()
                .eq(CouponHistoryEntity::getMemberId, loginInfoTO.getMemberId())
                .eq(CouponHistoryEntity::getGetType, CouponConstant.CouponHistoryGetType.GET.getCode())
                .select(CouponHistoryEntity::getCouponId));
        List<Long> couponHistory = couponHistoryEntityList.stream().map(CouponHistoryEntity::getCouponId).collect(Collectors.toList());

        List<CouponEntity> couponEntityList = baseMapper.getReceiveCoupon(
                CouponConstant.CouponType.MEMBER.getCode(),
                CouponConstant.CouponPublish.PUBLISH.getCode(),
                new Date(System.currentTimeMillis()),
                couponHistory);

        if(couponEntityList.isEmpty()){
            return R.ok().setData(new ArrayList<>());
        }

        List<CouponReceptionVO> couponReceptionVOList = CopyUtils.copyList(couponEntityList, CouponReceptionVO.class);
        List<Long> couponIdList = couponReceptionVOList.stream().map(CouponReceptionVO::getId).collect(Collectors.toList());

        List<CouponSpuRelationEntity> couponSpuRelationEntityList = couponSpuRelationService.getBaseMapper().selectList(new LambdaQueryWrapper<CouponSpuRelationEntity>()
                .in(CouponSpuRelationEntity::getCouponId, couponIdList));
        List<CouponSpuCategoryRelationEntity> couponSpuCategoryRelationEntityList = couponSpuCategoryRelationService.getBaseMapper().selectList(new LambdaQueryWrapper<CouponSpuCategoryRelationEntity>()
                .in(CouponSpuCategoryRelationEntity::getCouponId, couponIdList));

        for (CouponReceptionVO couponReceptionVO : couponReceptionVOList) {
            List<CouponReceptionVO.SpuOrCategoryVO> spuOrCategoryVOList = new ArrayList<>();

            if(CouponConstant.CouponUseType.CATEGORY.getCode().equals(couponReceptionVO.getUseType())){
                for (CouponSpuCategoryRelationEntity couponSpuCategoryRelationEntity : couponSpuCategoryRelationEntityList) {
                    if(couponReceptionVO.getId().equals(couponSpuCategoryRelationEntity.getCouponId())){
                        CouponReceptionVO.SpuOrCategoryVO spuOrCategoryVO = new CouponReceptionVO.SpuOrCategoryVO();
                        spuOrCategoryVO.setId(couponSpuCategoryRelationEntity.getCategoryId());
                        spuOrCategoryVO.setName(couponSpuCategoryRelationEntity.getCategoryName());
                        spuOrCategoryVOList.add(spuOrCategoryVO);
                    }
                }
            }

            if(CouponConstant.CouponUseType.PRODUCT.getCode().equals(couponReceptionVO.getUseType())){
                for (CouponSpuRelationEntity couponSpuRelationEntity : couponSpuRelationEntityList) {
                    if(couponReceptionVO.getId().equals(couponSpuRelationEntity.getCouponId())){
                        CouponReceptionVO.SpuOrCategoryVO spuOrCategoryVO = new CouponReceptionVO.SpuOrCategoryVO();
                        spuOrCategoryVO.setId(couponSpuRelationEntity.getSpuId());
                        spuOrCategoryVO.setName(couponSpuRelationEntity.getSpuName());
                        spuOrCategoryVOList.add(spuOrCategoryVO);
                    }
                }
            }

            couponReceptionVO.setSpuOrCategoryVOList(spuOrCategoryVOList);
        }

        LoginInterceptor.threadLocalID.remove();

        return R.ok().setData(couponReceptionVOList);
    }

    // 添加优惠券的分类和商品关系表
    private void addCategoryAndSpuRelation(CouponEntity couponEntity, List<CouponAddUpdateDTO.CouponDTO> couponDTO){
        // 指定分类
        if(CouponConstant.CouponUseType.CATEGORY.getCode().equals(couponEntity.getUseType())){
            List<CouponSpuCategoryRelationEntity> couponSpuCategoryRelationEntityList = new ArrayList<>();
            for (CouponAddUpdateDTO.CouponDTO dto : couponDTO) {
                CouponSpuCategoryRelationEntity couponSpuCategoryRelationEntity = new CouponSpuCategoryRelationEntity();
                couponSpuCategoryRelationEntity.setCouponId(couponEntity.getId());
                couponSpuCategoryRelationEntity.setCategoryId(dto.getId());
                couponSpuCategoryRelationEntity.setCategoryName(dto.getName());
                couponSpuCategoryRelationEntityList.add(couponSpuCategoryRelationEntity);
            }
            couponSpuCategoryRelationService.saveBatch(couponSpuCategoryRelationEntityList);
        }

        // 指定商品
        if(CouponConstant.CouponUseType.PRODUCT.getCode().equals(couponEntity.getUseType())){
            List<CouponSpuRelationEntity> couponSpuRelationEntityList = new ArrayList<>();
            for (CouponAddUpdateDTO.CouponDTO dto : couponDTO) {
                CouponSpuRelationEntity couponSpuRelationEntity = new CouponSpuRelationEntity();
                couponSpuRelationEntity.setCouponId(couponEntity.getId());
                couponSpuRelationEntity.setSpuId(dto.getId());
                couponSpuRelationEntity.setSpuName(dto.getName());
                couponSpuRelationEntityList.add(couponSpuRelationEntity);
            }
            couponSpuRelationService.saveBatch(couponSpuRelationEntityList);
        }
    }

}
